<!-- 模块说明 -->
<style lang="scss" scoped>
  .diy_form{
    display: flex;
    flex-wrap: wrap;
    .el-form-item{
      display: flex;
    :deep(.el-form-item__content){
        flex:1 !important;
        position: relative;
      }
    }
  }
</style>

<template>
  <div>
    <el-form
      :label-width="configs.labelWidth"
      :model="formValue.forms"
      ref="formRefs"
      :inline="configs.inline"
      :rules="configs.rule"
      :validate-on-rule-change="false"
      :disabled="configs.disabled || false"
      :size="configs.size || ''"
      class="diy_form"
    >
      <template v-for="(item, index) in options">
        <el-form-item
          :key="index + '-1'"
          :label="item.label"
          :prop="item.prop"
          :style="`width:${item.formItemWidth||configs.formItemWidth}`"
          v-if=" item.type != 'button' && !item.isHide"
        >
          <component
            :is="`el-${item.type}`"
            v-model="formValue.forms[item.prop]"
            :placeholder="item.placeholder || `${item.type === 'input' ? '请输入' : '请选择'}${item.label}`"
            :format="item.format ? item.format : 'YYYY-MM-DD'"
            :value-format="item.format ? item.format : 'YYYY-MM-DD'"
            :type="item.type === 'date-picker' ? item.dateType || 'date' : item.dateType ? item.dateType : ''"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            v-bind="item.attrs||{}"
            v-on="item.attrsFun||{}"
            :disabled="item.disabled"
            :readonly="item.readonly"
            style="width:100%"
          >
            <component
              v-for="(ele, i) in item.option?.data"
              :is="`el-${item.option.type}`"
              :key="i + '-2'"
              :label="ele.label"
              :value=" ele.value"
              :border="item.border"
            >
              {{ ele.label }}
            </component>
          </component>
          <div style="width:100%">
            <slot :name="item.prop" />
          </div>
        </el-form-item>
        <el-form-item
          :key="index + '-2'"
          v-if="item.type === 'button' && !item.isHide"
          :label="item.label"
          :style="`width:${item.formItemWidth||configs.formItemWidth}`"
        >
          <Buttons
            :options="item.options"
            :item-left="item.itemLeft || '10px'"
            :left="item.left || ''"
            :prop="formValue.forms"
            :disabled="item.disabled"
            style="width:100%"
          />
        </el-form-item>
      </template>
    </el-form>
  </div>
</template>

<script setup>
import { ref, reactive, defineProps, onMounted, defineEmits, watch, onBeforeMount } from 'vue'
import Buttons from '@/components/Buttons/index.vue'
import _ from 'lodash'
/**
   * @rules ===true 时 自动生成rules规则,配置项内规则会覆盖自动生成的
   * @inline 是否平铺
   * @formItemWidth formItem 长度 30%是为一行三个
   * @labelWidth label 的长度
   */

const configs = reactive({
  inline: true,
  formItemWidth: '45%',
  labelWidth: '145px',
  rules: false,
  rule: {}
})

const props = defineProps({
  formOptions: Array,
  config: Object
})
const formValue = reactive({ forms: {} })

//**********************************************************

/**
   * 动态生成rules
   */
const getRules = () => {
  let rule = {}
  props?.formOptions.forEach((ele) => {
    let str = ele.type === 'input' ? '请输入' : '请选择'
    if (ele.rules) {
      if (typeof ele.rules === 'function') {
        rule[ele.prop] = ele.rules(formValue.forms)
      } else {
        rule[ele.prop] = ele.rules
      }
    }
    if (props.config?.rules && !ele.rules) {
      rule[ele.prop] = [{ required: true, message: `${str}${ele.label}`, trigger: 'blur' }]
    }
  })
  configs.rule = rule
  formRefs.value && formRefs.value.clearValidate()
}

const options = ref([])
watch(
  () => formValue,
  () => {
    getRules()
    if (!props.formOptions.find((ele) => ele.isHide)) return
    options.value = _.cloneDeep(props.formOptions).map((ele) => {
      ele.isHide = ele?.isHide ? ele?.isHide(formValue.forms) : false
      return ele
    })
  },
  { deep: true }
)

/**生成默认值*/
let defaultValue = ref({}) //缓存初始表单数据用来
const getFormDefaultValue = () => {
  defaultValue.value = { ...formValue.forms }
  formValue.forms = props?.formOptions.reduce((total, item) => {
    total[item.prop] = item.type === 'checkbox-group' || item.type === 'checkboxGroup' ? [] : ''
    return total
  }, {})
  formValue.forms = { ...formValue.forms, ...defaultValue.value }
  defaultValue.value = { ...formValue.forms }
}

watch(
  () => props.formOptions,
  () => {
    options.value = _.cloneDeep(props.formOptions)
    getFormDefaultValue()
    getRules()
  },
  { deep: true }
)

/**
   * 返回config配置信息
   */
const backConfigs = () => {
  Object.keys(props.config).forEach((ele) => {
    configs[ele] = props.config[ele]
  })
}

/**
   * form实例
   */
const formRefs = ref(null)

/**
   * getForms 这个方法把 get set 以及form实例传递给父组件
   */
let emits = defineEmits(['getForms'])

onBeforeMount(() => {
  getFormDefaultValue()
})

/**
   * @params field为字符串时返回该字段的值
   * @params field为空 返回表单所有的值 (未添加表单校验,@getForms 方法返回form实例,请自行校验)
   */
const getValues = (field) => {
  if (field) {
    return formValue.forms[field]
  } else {
    let obj = {}
    options.value.forEach((ele) => {
      if (ele.type === 'date-picker' && Array.isArray(ele.mapping)) {
        try {
          obj[ele.mapping[0]] = formValue.forms[ele.prop][0]
          obj[ele.mapping[1]] = formValue.forms[ele.prop][1]
        } catch (error) {
          obj[ele.mapping[0]] = undefined
          obj[ele.mapping[1]] = undefined
        }
      }  else {
        obj[ele.prop] = formValue.forms[ele.prop]
      }
    })
    for (let key in obj) {
      if (!obj[key] && obj[key] !== 0 && obj[key] !== '0') {
        delete obj[key]
      }
    }
    return obj
  }
}

/**
   * @params _v === {key : value} 重置该字段key的值
   * @params _v === {}||空 重置该表单的值
   * @params _v === function 重置该表单的值后 调用这个function
   */
const setValues = (_v) => {
  new Promise((rej) => {
    if (typeof _v === 'function') {
      formValue.forms = { ...defaultValue.value }
      _v()
      rej()
    } else if (!_v || JSON.stringify(_v) === '{}') {
      formValue.forms = { ...defaultValue.value }
      rej()
    } else {
      let timer = setTimeout(() => {
        Object.keys(_v).forEach((ele) => {
          formValue.forms[ele] = _v[ele]
        })
        clearTimeout(timer)
        rej()
      }, 50)
    }
  }).then(() => {
    /**重置表单后会触发表单验证,这里需要异步清除表单验证*/
    formRefs.value && formRefs.value.clearValidate()
  })
}

  
onMounted(() => {
  emits('getForms', {
    _get: getValues,
    _set: setValues,
    _form: formRefs.value
  })
  options.value = _.cloneDeep(props.formOptions).map((ele) => {
    ele.isHide = ele?.isHide ? ele?.isHide(formValue.forms) : false
    return ele
  })
  backConfigs()
  getRules()
})

// const data = reactive({
//   formConfig: { inline: true, labelWidth: '120px', formItemWidth: '30%' },
//   formRefs: {},
//   options: [
//     {
//       type: 'input',
//       label: '输入框',
//       prop: 'input'
//     },
//     {
//       type: 'inputNumber',
//       label: '数字输入框',
//       prop: 'inputNumber',
//       attrs: {
//         //属性写这里
//         min: 1,
//         max: 10
//       },
//       attrsFun: {
//         //方法写这里
//         change: (e) => {
//           console.log(e)
//         }
//       }
//     },
//     {
//       type: 'select',
//       label: '下拉框',
//       prop: 'select',
//       attrs: {
//         clearable: true
//       },
//       option: {
//         type: 'option',
//         data: [{ label: '张三', value: 'zhangsan' }, { label: '李四', value: 'lisi' }]
//       }
//     },
//     {
//       type: 'radioGroup',
//       label: '单选框',
//       prop: 'radioGroup',
//       option: {
//         type: 'radio',
//         data: [{ label: '张三', value: 'zhangsan' }, { label: '李四', value: 'lisi' }]
//       }
//     },
//     {
//       type: 'rate',
//       label: '评分',
//       prop: 'rate',
//       attrs: {
//         colors: 5
//       }
//     },
//     {
//       type: 'slider',
//       label: '滑块',
//       prop: 'slider'
//     },
//     {
//       type: 'switch',
//       label: '开关',
//       prop: 'switch'
//     },
//     {
//       type: 'checkbox-group',
//       label: '多选框',
//       prop: 'checkboxGroup',
//       formItemWidth: '100%',
//       option: {
//         type: 'checkbox',
//         data: [{ label: '张三', value: 'zhangsan' }, { label: '李四', value: ';lisi' }, { label: '王五', value: 'wangwu' }, { label: '王五1', value: 'wangwu1' }, { label: '王五2', value: 'wangwu2' }]
//       }
//     },
//     {
//       type: 'date-picker',
//       label: '时间选择',
//       prop: 'datePicker'
//     },
//     {
//       type: 'date-picker',
//       label: '时间选择',
//       dateType: 'daterange',
//       prop: 'promisePayDate', //随便写但同一个form不允许重复
//       mapping: ['promisePayDateStart', 'promisePayDateEnd']//返回字段的映射值
//     },
//     {
//       type: 'diySolt',
//       label: '自定义插槽',
//       prop: 'diySolt'
//     },
//     {
//       type: 'button',
//       label: '按钮',
//       formItemWidth: '100%',
//       options: [
//         {
//           text: '默认按钮'
//         },
//         {
//           text: 'Primary',
//           type: 'primary'
//         },
//         {
//           text: 'Success',
//           type: 'success'
//         },
//         {
//           text: 'Info',
//           type: 'info'
//         },
//         {
//           type: 'danger',
//           icon: Search,
//           attrs: {
//             circle: true
//           }
//         },
//         {
//           text: 'Warning',
//           type: 'warning',
//           icon: Edit
//         }
//       ]
//     }
//   ]
// })
</script>
